from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
import logging

_logger = logging.getLogger(__name__)


class DingTalkEmployee(models.Model):
    _name = 'dingtalk.employee'
    _description = '钉钉员工'
    _rec_name = 'name'
    _order = 'name'
    
    name = fields.Char(string="姓名", required=True)
    userid = fields.Char(string="钉钉 UserID", required=True, index=True,
                        help="钉钉系统中的用户ID")
    unionid = fields.Char(string="钉钉 UnionID", index=True, copy=False,
                          help="钉钉开放平台的唯一ID，用于跨应用识别用户")
    
    # 联系信息
    mobile = fields.Char(string="手机号")
    email = fields.Char(string="邮箱")
    telephone = fields.Char(string="分机号")
    
    # 职位信息
    position = fields.Char(string="职位")
    job_number = fields.Char(string="工号")
    title = fields.Char(string="职务")
    
    # 部门信息
    department_id = fields.Many2one('dingtalk.department', string="主部门", 
                                   index=True, ondelete='set null')
    department_ids = fields.Many2many('dingtalk.department', 
                                     'dingtalk_employee_department_rel',
                                     'employee_id', 'department_id',
                                     string="所属部门")
    
    # 头像
    avatar = fields.Char(string="头像URL")
    
    # 状态
    active_status = fields.Selection([
        ('active', '在职'),
        ('inactive', '离职'),
    ], string="在职状态", default='active')
    
    # 同步信息
    last_sync_time = fields.Datetime(string="最后同步时间", readonly=True)
    sync_status = fields.Selection([
        ('synced', '已同步'),
        ('error', '同步失败'),
        ('pending', '待同步'),
    ], string="同步状态", default='pending')
    
    active = fields.Boolean(string="启用", default=True)
    
    # 关联到 Odoo 用户
    user_id = fields.Many2one('res.users', string="关联用户", readonly=True, 
                             help="该钉钉员工对应的 Odoo 系统用户")
    is_odoo_user = fields.Boolean(string="已是系统用户", compute='_compute_is_odoo_user', 
                                  store=True, help="该员工是否已转为 Odoo 用户")
    
    _sql_constraints = [
        ('userid_unique', 'UNIQUE(userid)', '钉钉 UserID 必须唯一！'),
    ]
    
    @api.depends('user_id')
    def _compute_is_odoo_user(self):
        """计算是否已是系统用户"""
        for record in self:
            record.is_odoo_user = bool(record.user_id)
    
    def action_convert_to_users(self):
        """将选中的钉钉员工转为 Odoo 系统用户（支持重复转换以更新字段）"""
        
        created_count = 0
        updated_count = 0
        skipped_count = 0
        error_list = []
        
        for employee in self:
            try:
                # 验证必要字段
                if not employee.email:
                    error_list.append(f"{employee.name}：缺少邮箱地址")
                    _logger.warning(f"⚠️  {employee.name} 缺少邮箱，无法创建用户")
                    continue
                
                # 检查是否已有关联用户
                if employee.user_id:
                    # 已有关联用户，更新钉钉字段（如果字段已启用）
                    _logger.info(f"🔄 {employee.name} 已有关联用户，更新钉钉字段...")
                    
                    # 准备要更新的钉钉字段
                    update_vals = {}
                    
                    # 检查 dingtalk_userid 字段是否存在（已启用）
                    if 'dingtalk_userid' in self.env['res.users']._fields:
                        update_vals['dingtalk_userid'] = employee.userid
                        if employee.unionid:
                            update_vals['dingtalk_unionid'] = employee.unionid
                        update_vals['dingtalk_employee_id'] = employee.id
                        
                        employee.user_id.sudo().write(update_vals)
                        _logger.info(f"  ✅ 已更新钉钉字段: userid={employee.userid}, unionid={employee.unionid}")
                        updated_count += 1
                    else:
                        _logger.info(f"  ⏭️  跳过：钉钉字段尚未启用（需要先启用 res.users 中的钉钉字段）")
                        skipped_count += 1
                    continue
                
                # 检查邮箱是否已被其他用户使用
                existing_user = self.env['res.users'].sudo().search([
                    ('login', '=', employee.email)
                ], limit=1)
                
                if existing_user:
                    # 如果用户已存在，关联并更新字段
                    employee.user_id = existing_user.id
                    
                    # 更新钉钉字段（如果已启用）
                    if 'dingtalk_userid' in self.env['res.users']._fields:
                        existing_user.sudo().write({
                            'dingtalk_userid': employee.userid,
                            'dingtalk_unionid': employee.unionid,
                            'dingtalk_employee_id': employee.id,
                        })
                        _logger.info(f"🔗 {employee.name} 关联到已存在的用户: {existing_user.login}，并更新钉钉字段")
                    else:
                        _logger.info(f"🔗 {employee.name} 关联到已存在的用户: {existing_user.login}")
                    
                    created_count += 1
                    continue
                
                # 创建新用户
                user_vals = {
                    'name': employee.name,
                    'login': employee.email,
                    'email': employee.email,
                    'phone': employee.mobile or False,
                    'active': employee.active_status == 'active',
                    'groups_id': [(6, 0, [self.env.ref('base.group_user').id])],  # 默认为普通用户
                }
                
                # 如果钉钉字段已启用，添加钉钉信息
                if 'dingtalk_userid' in self.env['res.users']._fields:
                    user_vals['dingtalk_userid'] = employee.userid
                    if employee.unionid:
                        user_vals['dingtalk_unionid'] = employee.unionid
                    user_vals['dingtalk_employee_id'] = employee.id
                    _logger.info(f"  ✅ 将设置钉钉字段")
                
                new_user = self.env['res.users'].sudo().create(user_vals)
                employee.user_id = new_user.id
                
                _logger.info(f"✅ 成功为 {employee.name} 创建用户: {new_user.login}")
                created_count += 1
                
            except Exception as e:
                error_msg = f"{employee.name}：{str(e)}"
                error_list.append(error_msg)
                _logger.error(f"❌ 创建用户失败: {error_msg}")
        
        # 返回结果通知
        if created_count > 0 or updated_count > 0 or skipped_count > 0:
            parts = []
            if created_count > 0:
                parts.append(_('创建 %d 个') % created_count)
            if updated_count > 0:
                parts.append(_('更新 %d 个') % updated_count)
            if skipped_count > 0:
                parts.append(_('跳过 %d 个') % skipped_count)
            
            message = _('成功！') + ' ' + ', '.join(parts)
            if error_list:
                message += _('\n\n失败 %d 个：\n') % len(error_list)
                message += '\n'.join(error_list[:5])  # 只显示前5个错误
                if len(error_list) > 5:
                    message += f'\n... 还有 {len(error_list) - 5} 个错误'
            
            notification_type = 'success' if not error_list else 'warning'
        else:
            message = _('转换失败！\n\n') + '\n'.join(error_list)
            notification_type = 'danger'
        
        return {
            'type': 'ir.actions.client',
            'tag': 'display_notification',
            'params': {
                'title': _('转为系统用户'),
                'message': message,
                'type': notification_type,
                'sticky': True,
            }
        }
    
    @api.model
    def sync_from_dingtalk(self):
        """从钉钉同步所有员工"""
        config = self.env['dingtalk.config'].get_default_config()
        access_token = config.get_valid_access_token()
        api = config._get_api_client()
        
        _logger.info("=" * 80)
        _logger.info("开始同步钉钉员工...")
        
        # 获取所有部门
        departments = self.env['dingtalk.department'].search([])
        
        if not departments:
            raise ValidationError(_('请先同步部门架构'))
        
        created_count = 0
        updated_count = 0
        error_count = 0
        
        for dept in departments:
            _logger.info(f"同步部门 {dept.name} 的员工...")
            
            # 获取部门用户ID列表
            user_ids = api.get_department_user_list(access_token, dept.dept_id)
            _logger.info(f"  部门 {dept.name} 有 {len(user_ids)} 个员工")
            
            for userid in user_ids:
                try:
                    # 获取用户详细信息
                    user_data = api.get_user_detail(access_token, userid)
                    
                    if not user_data:
                        error_count += 1
                        continue
                    
                    # 查找是否已存在
                    existing = self.search([('userid', '=', userid)], limit=1)
                    
                    # 准备数据 - 优先使用 org_email，如果没有再用 email
                    email = user_data.get('org_email') or user_data.get('email') or ''
                    unionid = user_data.get('unionid', '')
                    
                    vals = {
                        'name': user_data.get('name'),
                        'userid': userid,
                        'unionid': unionid,  # 保存 UnionID，用于 OAuth 登录
                        'mobile': user_data.get('mobile', ''),
                        'email': email,  # 使用企业邮箱或个人邮箱
                        'telephone': user_data.get('telephone', ''),
                        'position': user_data.get('position', ''),
                        'job_number': user_data.get('job_number', ''),
                        'title': user_data.get('title', ''),
                        'avatar': user_data.get('avatar', ''),
                        'active_status': 'active' if user_data.get('active', True) else 'inactive',
                        'last_sync_time': fields.Datetime.now(),
                        'sync_status': 'synced',
                    }
                    
                    _logger.info(f"  📧 邮箱: {email} (org_email: {user_data.get('org_email')}, email: {user_data.get('email')})")
                    _logger.info(f"  🔑 UnionID: {unionid}")
                    
                    # 设置主部门（第一个部门）
                    dept_id_list = user_data.get('dept_id_list', [])
                    if dept_id_list:
                        main_dept = self.env['dingtalk.department'].search([
                            ('dept_id', '=', str(dept_id_list[0]))
                        ], limit=1)
                        if main_dept:
                            vals['department_id'] = main_dept.id
                    
                    if existing:
                        existing.write(vals)
                        
                        # 更新所属部门（Many2many）
                        all_depts = self.env['dingtalk.department'].search([
                            ('dept_id', 'in', [str(d) for d in dept_id_list])
                        ])
                        existing.department_ids = [(6, 0, all_depts.ids)]
                        
                        updated_count += 1
                        _logger.info(f"    ✅ 更新员工: {user_data.get('name')} ({userid})")
                    else:
                        new_emp = self.create(vals)
                        
                        # 设置所属部门
                        all_depts = self.env['dingtalk.department'].search([
                            ('dept_id', 'in', [str(d) for d in dept_id_list])
                        ])
                        new_emp.department_ids = [(6, 0, all_depts.ids)]
                        
                        created_count += 1
                        _logger.info(f"    ✨ 创建员工: {user_data.get('name')} ({userid})")
                        
                except Exception as e:
                    error_count += 1
                    _logger.error(f"    ❌ 处理员工失败 {userid}: {str(e)}")
        
        # 更新配置统计
        total_employees = self.search_count([])
        config.sudo().write({
            'total_employees': total_employees,
        })
        
        _logger.info("=" * 80)
        _logger.info(f"✅ 员工同步完成！")
        _logger.info(f"  创建: {created_count}")
        _logger.info(f"  更新: {updated_count}")
        _logger.info(f"  失败: {error_count}")
        _logger.info(f"  总计: {total_employees}")
        _logger.info("=" * 80)
        
        return {
            'type': 'ir.actions.client',
            'tag': 'display_notification',
            'params': {
                'title': _('同步完成'),
                'message': _('成功同步 %d 个员工（创建 %d，更新 %d）') % (
                    total_employees, created_count, updated_count
                ),
                'type': 'success',
                'sticky': False,
            }
        }
    
    @api.model
    def sync_department_employees(self, dept_id):
        """同步指定部门的员工"""
        config = self.env['dingtalk.config'].get_default_config()
        access_token = config.get_valid_access_token()
        api = config._get_api_client()
        
        # 获取部门用户
        user_ids = api.get_department_user_list(access_token, dept_id)
        
        for userid in user_ids:
            user_data = api.get_user_detail(access_token, userid)
            if user_data:
                # 创建或更新员工
                self._create_or_update_employee(user_data)
        
        return True
    
    def _create_or_update_employee(self, user_data):
        """创建或更新员工记录"""
        userid = user_data.get('userid')
        existing = self.search([('userid', '=', userid)], limit=1)
        
        # 优先使用 org_email，如果没有再用 email
        email = user_data.get('org_email') or user_data.get('email') or ''
        unionid = user_data.get('unionid', '')
        
        vals = {
            'name': user_data.get('name'),
            'userid': userid,
            'unionid': unionid,  # 保存 UnionID
            'mobile': user_data.get('mobile', ''),
            'email': email,  # 使用企业邮箱或个人邮箱
            'position': user_data.get('position', ''),
            'last_sync_time': fields.Datetime.now(),
            'sync_status': 'synced',
        }
        
        if existing:
            existing.write(vals)
            return existing
        else:
            return self.create(vals)

